package com.tocici.api;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedissonLockExecutor;
import com.tocici.domain.bo.MusicBo;
import com.tocici.domain.bo.UserBehaviorBo;
import com.tocici.domain.bo.UserCateRelationBo;
import com.tocici.domain.vo.MusicVo;
import com.tocici.domain.vo.UserBehaviorVo;
import com.tocici.domain.vo.UserCateRelationVo;
import com.tocici.service.IMusicService;
import com.tocici.service.IUserBehaviorService;
import com.tocici.service.IUserCateRelationService;
import lombok.RequiredArgsConstructor;
import org.apache.mahout.cf.taste.common.TasteException;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.system.service.ISysConfigService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.sql.SQLException;
import java.util.List;

@RestController
@RequestMapping("/app")
@RequiredArgsConstructor
@SaIgnore
public class AppIndexAPI {

    private final IMusicService musicService;

    private final IUserBehaviorService userBehaviorService;

    private final LockTemplate lockTemplate;

    private final IUserCateRelationService userCateRelationService;

    private final ISysConfigService configService;

    @GetMapping("/index/search/{keyword}")
    public R<List<MusicVo>> search(@PathVariable String keyword){
        List<MusicVo> search = musicService.search(keyword);
        return R.ok(search);
    }

    @GetMapping("/index/stat/{musicId}")
    public R<Void> uploadUserBehavior(@PathVariable Long musicId){
        String id = StpUtil.getExtra("userId").toString();
        Long userId = Long.valueOf(id);
        UserBehaviorBo bo = new UserBehaviorBo();
        bo.setUserId(userId);
        bo.setMusicId(musicId);
//        todo: 这里还需要加上用户听歌时长，听歌时段的统计
        List<UserBehaviorVo> userBehaviorVos = userBehaviorService.queryList(bo);
//        这里是判断用户第一次听这首歌，插入用户行为记录
        if (userBehaviorVos.isEmpty()){
            bo.setIsLiked(0);
            MusicVo musicVo = musicService.queryById(musicId);
            UserCateRelationBo userCateRelationBo = new UserCateRelationBo();
            userCateRelationBo.setCateId(musicVo.getCategoryId());
            userCateRelationBo.setUserId(userId);
            List<UserCateRelationVo> userCateRelationVos = userCateRelationService.queryList(userCateRelationBo);
            bo.setInCateCollect(userCateRelationVos.isEmpty() ? 0:1);
            userBehaviorService.insertByBo(bo);
        }else{
            UserBehaviorVo userBehaviorVo = userBehaviorVos.get(0);
            UserBehaviorBo bean = BeanUtil.toBean(userBehaviorVo, UserBehaviorBo.class);
            bean.setPlayCount(bean.getPlayCount()+1);
            userBehaviorService.updateByBo(bean);

        }
//        获取分布式锁
        final LockInfo lock = lockTemplate.lock(musicId.toString(), 30000L, 5000L, RedissonLockExecutor.class);
        if (null == lock){
            throw new ServiceException("业务繁忙，请稍后再试");
        }
        try {
            MusicVo musicVo = musicService.queryById(musicId);
            MusicBo bean = BeanUtil.toBean(musicVo, MusicBo.class);
            bean.setPlayCount(bean.getPlayCount()+1);
            musicService.updateByBo(bean);
        }finally {
            lockTemplate.releaseLock(lock);
        }
        return R.ok();

    }

    @GetMapping("/like/{musicId}")
    public R<Void> likeMusic(@PathVariable Long musicId){
        String id = StpUtil.getExtra("userId").toString();
        Long userId = Long.valueOf(id);
        UserBehaviorBo bo = new UserBehaviorBo();
        bo.setUserId(userId);
        bo.setMusicId(musicId);
        List<UserBehaviorVo> userBehaviorVos = userBehaviorService.queryList(bo);
        if (userBehaviorVos.isEmpty()){
            throw new ServiceException("还没有该歌曲的行为记录");
        }
        UserBehaviorVo userBehaviorVo = userBehaviorVos.get(0);
        BeanUtil.copyProperties(userBehaviorVo,bo);
        if (userBehaviorVos.get(0).getIsLiked().equals(0)){
            bo.setIsLiked(1);
        }else{
            bo.setIsLiked(0);
        }
        userBehaviorService.updateByBo(bo);
        return R.ok();
    }

    @GetMapping("/userBehavior/{musicId}")
    public R<UserBehaviorVo> getUserBehaviorByMusic(@PathVariable Long musicId){
        String id = StpUtil.getExtra("userId").toString();
        Long userId = Long.valueOf(id);
        UserBehaviorBo bo = new UserBehaviorBo();
        bo.setUserId(userId);
        bo.setMusicId(musicId);
        List<UserBehaviorVo> userBehaviorVos = userBehaviorService.queryList(bo);
        if (userBehaviorVos.size()>1){
            throw new ServiceException("记录异常");
        }
        return R.ok(userBehaviorVos.get(0));

    }

    @GetMapping("/recommend")
    public R<List<MusicVo>> getRecommend(){
        String id = StpUtil.getExtra("userId").toString();
        Long userId = Long.valueOf(id);
        try {
            String s = configService.selectConfigByKey("app.index.recommend");

            List<MusicVo> list = musicService.getRecommend(userId);
            return R.ok("filter".equals(s)?"协同过滤":"apriori算法",list);
        } catch (TasteException e) {
            throw new ServiceException("推荐异常");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}
